module booth2_16x16_8x8 (
			 output logic [31:0] o_result,
			 input logic [15:0]  i_a, // multiplicand
			 input logic [15:0]  i_b, // multiplier
			 input logic 	     i_sign,
			 input logic 	     i_mode // 0:16x16, 1:two 8x8
			 );
   //for 16-bit mode
   wire [15+1:0] 		 a_16 = {i_sign & i_a[15], i_a[15:0]};
   wire [7+1:0] 		 a_8_h = {i_sign & i_a[15], i_a[15:8]};
   wire [7+1:0] 		 a_8_l = {i_sign & i_a[7], i_a[7:0]};

   wire [15+2:0] 		 b_16 = {{2{i_sign & i_b[15]}}, i_b[15:0]}; // extend 2 bits for booth2 recoding
   wire [15+3:0] 		 b_16_ext = {b_16, 1'b0};
      
		 
   logic [15+1:0] 		 pp[8:0]; // total 9 PPs			// FIXME: pp[width/2:0]  // width/2+1
   logic 			 S[8:0];  // the last one is not needed (must be 0)
   logic 			 E[8:0];  // the last one is not needed

   logic [31:0] 		 final_pp0, final_pp1;
   logic [31:0] 		 result; // the real result may be a signed number 


   wire 			 mode = i_mode;
   

   // ==================== for simulation ====================
   logic signed [2:0] 		 booth_array_sim[8:0]; // 0, +-1, +-2
   logic signed [15+1:0] 	 pp_sim[8:0];
   logic 			 S_sim[8:0];
   logic 			 E_sim[8:0];
   logic [3:0] 			 cols_sim[31:0]; // the max column height is 9, so must use 4 bits to represent
   

   //logic signed [15+1:0] 	 pp_actual[8:0];
   logic signed [31:0] 		 pp_actual_sim[8:0]; // 17 bits or 32bits ????
   
      

   wire [15+1:0] 		 a_mix;
   
   
   // for 16-bit mode
   // ========== generate PPs and sign compensation : S, E ==========
   generate
      genvar 			 i;
      for(i=0;i<9;i++)
	begin : mul_pps
	   booth2_pp_gen #(16+1) unit // mul_pps[1].unit.xxx, the width of PP should one more than the input width
	    (
	     .pp_out(pp[i]),
	     .pp_s(S[i]),
	     .pp_e(E[i]),
	     
	     .mcand(a_mix),				// multiplicand
	     .booth2(b_16_ext[i*2+2:i*2])	// booth2 code of multiplier
	     );
	end // block: mul_pp
   endgenerate


// ==================== compress ====================
   logic S1_1_1,S1_1_0,S1_3_1,S1_4_2,S1_5_2,S1_4_1,S1_6_2,S1_7_2,S1_7_3,S1_8_3,S1_7_1,S1_9_2,S1_9_3,S1_10_3,S1_10_4,S1_11_3,S1_11_4,S1_10_2,S1_12_3,S1_12_4,S1_13_3,S1_13_4,S1_13_5,S1_14_4,S1_14_5,S1_13_2,S1_15_3,S1_15_4,S1_15_5,S1_16_4,S1_16_5,S1_16_6,S1_17_4,S1_17_5,S1_17_6,S1_18_4,S1_18_5,S1_18_6,S1_19_4,S1_19_5,S1_19_6,S1_20_3,S1_20_4,S1_20_5,S1_21_3,S1_21_4,S1_21_5,S1_22_3,S1_22_4,S1_21_2,S1_23_3,S1_23_4,S1_22_2,S1_24_3,S1_24_4,S1_25_2,S1_25_3,S1_26_2,S1_26_3,S1_27_2,S1_27_3,S1_28_2,S1_27_1,S1_29_2,S1_28_1,S1_30_2,S1_31_1,S1_32_Carry_0;
logic S2_0_0,S2_2_1,S2_2_0,S2_4_2,S2_5_1,S2_6_2,S2_7_2,S2_8_2,S2_7_1,S2_9_2,S2_10_2,S2_9_1,S2_11_2,S2_11_3,S2_12_2,S2_11_1,S2_13_3,S2_13_4,S2_14_2,S2_14_3,S2_15_3,S2_15_4,S2_16_3,S2_16_4,S2_17_3,S2_17_4,S2_18_3,S2_18_4,S2_19_3,S2_19_4,S2_20_3,S2_20_4,S2_21_3,S2_21_4,S2_22_2,S2_22_3,S2_23_2,S2_23_3,S2_24_2,S2_23_1,S2_25_2,S2_24_1,S2_26_2,S2_25_1,S2_27_2,S2_26_1,S2_28_2,S2_27_1,S2_29_1,S2_30_1,S2_31_1,S2_32_Carry_0;
logic S3_0_0,S3_1_0,S3_3_1,S3_3_0,S3_5_1,S3_6_1,S3_7_2,S3_8_1,S3_9_2,S3_10_2,S3_11_2,S3_12_2,S3_11_1,S3_13_2,S3_14_2,S3_13_1,S3_15_2,S3_14_1,S3_16_2,S3_15_1,S3_17_2,S3_16_1,S3_18_2,S3_17_1,S3_19_2,S3_18_1,S3_20_2,S3_19_1,S3_21_2,S3_20_1,S3_22_2,S3_21_1,S3_23_2,S3_22_1,S3_24_2,S3_23_1,S3_25_2,S3_26_2,S3_27_2,S3_28_1,S3_29_1,S3_30_1,S3_31_1,S3_32_Carry_0;
logic S4_0_0,S4_1_0,S4_2_0,S4_4_1,S4_4_0,S4_6_1,S4_7_1,S4_8_1,S4_9_1,S4_10_1,S4_11_2,S4_12_1,S4_13_2,S4_14_2,S4_15_2,S4_16_2,S4_17_2,S4_18_2,S4_19_2,S4_20_2,S4_21_2,S4_22_2,S4_23_2,S4_24_1,S4_25_1,S4_26_1,S4_27_1,S4_28_1,S4_29_1,S4_30_1,S4_31_1,S4_32_Carry_0;
// ==================== Stage1 ====================
HA ha1 (S1_1_1,S1_0_0,pp[0][0],S[0]);
assign S1_1_0 = pp[0][1];
FA fa1 (S1_3_1,S1_2_0,pp[0][2],pp[1][0],S[1]);
HA ha2 (S1_4_2,S1_3_0,pp[0][3],pp[1][1]);
FA fa2 (S1_5_2,S1_4_0,pp[0][4],pp[1][2],pp[2][0]);
assign S1_4_1 = S[2];
FA fa3 (S1_6_2,S1_5_0,pp[0][5],pp[1][3],pp[2][1]);
FA fa4 (S1_7_2,S1_6_0,pp[0][6],pp[1][4],pp[2][2]);
HA ha3 (S1_7_3,S1_6_1,pp[3][0],S[3]);
FA fa5 (S1_8_3,S1_7_0,pp[0][7],pp[1][5],pp[2][3]);
assign S1_7_1 = pp[3][1];
FA fa6 (S1_9_2,S1_8_0,pp[0][8],pp[1][6],pp[2][4]);
FA fa7 (S1_9_3,S1_8_1,pp[3][2],pp[4][0],S[4]);
FA fa8 (S1_10_3,S1_9_0,pp[0][9],pp[1][7],pp[2][5]);
HA ha4 (S1_10_4,S1_9_1,pp[3][3],pp[4][1]);
FA fa9 (S1_11_3,S1_10_0,pp[0][10],pp[1][8],pp[2][6]);
FA fa10 (S1_11_4,S1_10_1,pp[3][4],pp[4][2],pp[5][0]);
assign S1_10_2 = S[5];
FA fa11 (S1_12_3,S1_11_0,pp[0][11],pp[1][9],pp[2][7]);
FA fa12 (S1_12_4,S1_11_1,pp[3][5],pp[4][3],pp[5][1]);
FA fa13 (S1_13_3,S1_12_0,pp[0][12],pp[1][10],pp[2][8]);
FA fa14 (S1_13_4,S1_12_1,pp[3][6],pp[4][4],pp[5][2]);
HA ha5 (S1_13_5,S1_12_2,pp[6][0],S[6]);
FA fa15 (S1_14_4,S1_13_0,pp[0][13],pp[1][11],pp[2][9]);
FA fa16 (S1_14_5,S1_13_1,pp[3][7],pp[4][5],pp[5][3]);
assign S1_13_2 = pp[6][1];
FA fa17 (S1_15_3,S1_14_0,pp[0][14],pp[1][12],pp[2][10]);
FA fa18 (S1_15_4,S1_14_1,pp[3][8],pp[4][6],pp[5][4]);
FA fa19 (S1_15_5,S1_14_2,pp[6][2],pp[7][0],S[7]);
FA fa20 (S1_16_4,S1_15_0,pp[0][15],pp[1][13],pp[2][11]);
FA fa21 (S1_16_5,S1_15_1,pp[3][9],pp[4][7],pp[5][5]);
HA ha6 (S1_16_6,S1_15_2,pp[6][3],pp[7][1]);
FA fa22 (S1_17_4,S1_16_0,pp[0][16],pp[1][14],pp[2][12]);
FA fa23 (S1_17_5,S1_16_1,pp[3][10],pp[4][8],pp[5][6]);
FA fa24 (S1_17_6,S1_16_2,pp[6][4],pp[7][2],pp[8][0]);
FA fa25 (S1_18_4,S1_17_0,{~E[0]},pp[1][15],pp[2][13]);
FA fa26 (S1_18_5,S1_17_1,pp[3][11],pp[4][9],pp[5][7]);
FA fa27 (S1_18_6,S1_17_2,pp[6][5],pp[7][3],pp[8][1]);
FA fa28 (S1_19_4,S1_18_0,{~E[0]},pp[1][16],pp[2][14]);
FA fa29 (S1_19_5,S1_18_1,pp[3][12],pp[4][10],pp[5][8]);
FA fa30 (S1_19_6,S1_18_2,pp[6][6],pp[7][4],pp[8][2]);
FA fa31 (S1_20_3,S1_19_0,E[0],E[1],pp[2][15]);
FA fa32 (S1_20_4,S1_19_1,pp[3][13],pp[4][11],pp[5][9]);
FA fa33 (S1_20_5,S1_19_2,pp[6][7],pp[7][5],pp[8][3]);
FA fa34 (S1_21_3,S1_20_0,1'b1,pp[2][16],pp[3][14]);
FA fa35 (S1_21_4,S1_20_1,pp[4][12],pp[5][10],pp[6][8]);
HA ha7 (S1_21_5,S1_20_2,pp[7][6],pp[8][4]);
FA fa36 (S1_22_3,S1_21_0,E[2],pp[3][15],pp[4][13]);
FA fa37 (S1_22_4,S1_21_1,pp[5][11],pp[6][9],pp[7][7]);
assign S1_21_2 = pp[8][5];
FA fa38 (S1_23_3,S1_22_0,1'b1,pp[3][16],pp[4][14]);
FA fa39 (S1_23_4,S1_22_1,pp[5][12],pp[6][10],pp[7][8]);
assign S1_22_2 = pp[8][6];
FA fa40 (S1_24_3,S1_23_0,E[3],pp[4][15],pp[5][13]);
FA fa41 (S1_24_4,S1_23_1,pp[6][11],pp[7][9],pp[8][7]);
FA fa42 (S1_25_2,S1_24_0,1'b1,pp[4][16],pp[5][14]);
FA fa43 (S1_25_3,S1_24_1,pp[6][12],pp[7][10],pp[8][8]);
FA fa44 (S1_26_2,S1_25_0,E[4],pp[5][15],pp[6][13]);
HA ha8 (S1_26_3,S1_25_1,pp[7][11],pp[8][9]);
FA fa45 (S1_27_2,S1_26_0,1'b1,pp[5][16],pp[6][14]);
HA ha9 (S1_27_3,S1_26_1,pp[7][12],pp[8][10]);
FA fa46 (S1_28_2,S1_27_0,E[5],pp[6][15],pp[7][13]);
assign S1_27_1 = pp[8][11];
FA fa47 (S1_29_2,S1_28_0,1'b1,pp[6][16],pp[7][14]);
assign S1_28_1 = pp[8][12];
FA fa48 (S1_30_2,S1_29_0,E[6],pp[7][15],pp[8][13]);
FA fa49 (S1_31_1,S1_30_0,1'b1,pp[7][16],pp[8][14]);
HA ha10 (S1_32_Carry_0,S1_31_0,E[7],pp[8][15]);
// ==================== Stage2 ====================
assign S2_0_0 = S1_0_0;
HA ha11 (S2_2_1,S2_1_0,S1_1_0,S1_1_1);
assign S2_2_0 = S1_2_0;
HA ha12 (S2_4_2,S2_3_0,S1_3_0,S1_3_1);
FA fa50 (S2_5_1,S2_4_0,S1_4_0,S1_4_1,S1_4_2);
HA ha13 (S2_6_2,S2_5_0,S1_5_0,S1_5_2);
FA fa51 (S2_7_2,S2_6_0,S1_6_0,S1_6_1,S1_6_2);
FA fa52 (S2_8_2,S2_7_0,S1_7_0,S1_7_1,S1_7_2);
assign S2_7_1 = S1_7_3;
FA fa53 (S2_9_2,S2_8_0,S1_8_0,S1_8_1,S1_8_3);
FA fa54 (S2_10_2,S2_9_0,S1_9_0,S1_9_1,S1_9_2);
assign S2_9_1 = S1_9_3;
FA fa55 (S2_11_2,S2_10_0,S1_10_0,S1_10_1,S1_10_2);
HA ha14 (S2_11_3,S2_10_1,S1_10_3,S1_10_4);
FA fa56 (S2_12_2,S2_11_0,S1_11_0,S1_11_1,S1_11_3);
assign S2_11_1 = S1_11_4;
FA fa57 (S2_13_3,S2_12_0,S1_12_0,S1_12_1,S1_12_2);
HA ha15 (S2_13_4,S2_12_1,S1_12_3,S1_12_4);
FA fa58 (S2_14_2,S2_13_0,S1_13_0,S1_13_1,S1_13_2);
FA fa59 (S2_14_3,S2_13_1,S1_13_3,S1_13_4,S1_13_5);
FA fa60 (S2_15_3,S2_14_0,S1_14_0,S1_14_1,S1_14_2);
HA ha16 (S2_15_4,S2_14_1,S1_14_4,S1_14_5);
FA fa61 (S2_16_3,S2_15_0,S1_15_0,S1_15_1,S1_15_2);
FA fa62 (S2_16_4,S2_15_1,S1_15_3,S1_15_4,S1_15_5);
FA fa63 (S2_17_3,S2_16_0,S1_16_0,S1_16_1,S1_16_2);
FA fa64 (S2_17_4,S2_16_1,S1_16_4,S1_16_5,S1_16_6);
FA fa65 (S2_18_3,S2_17_0,S1_17_0,S1_17_1,S1_17_2);
FA fa66 (S2_18_4,S2_17_1,S1_17_4,S1_17_5,S1_17_6);
FA fa67 (S2_19_3,S2_18_0,S1_18_0,S1_18_1,S1_18_2);
FA fa68 (S2_19_4,S2_18_1,S1_18_4,S1_18_5,S1_18_6);
FA fa69 (S2_20_3,S2_19_0,S1_19_0,S1_19_1,S1_19_2);
FA fa70 (S2_20_4,S2_19_1,S1_19_4,S1_19_5,S1_19_6);
FA fa71 (S2_21_3,S2_20_0,S1_20_0,S1_20_1,S1_20_2);
FA fa72 (S2_21_4,S2_20_1,S1_20_3,S1_20_4,S1_20_5);
FA fa73 (S2_22_2,S2_21_0,S1_21_0,S1_21_1,S1_21_2);
FA fa74 (S2_22_3,S2_21_1,S1_21_3,S1_21_4,S1_21_5);
FA fa75 (S2_23_2,S2_22_0,S1_22_0,S1_22_1,S1_22_2);
HA ha17 (S2_23_3,S2_22_1,S1_22_3,S1_22_4);
FA fa76 (S2_24_2,S2_23_0,S1_23_0,S1_23_1,S1_23_3);
assign S2_23_1 = S1_23_4;
FA fa77 (S2_25_2,S2_24_0,S1_24_0,S1_24_1,S1_24_3);
assign S2_24_1 = S1_24_4;
FA fa78 (S2_26_2,S2_25_0,S1_25_0,S1_25_1,S1_25_2);
assign S2_25_1 = S1_25_3;
FA fa79 (S2_27_2,S2_26_0,S1_26_0,S1_26_1,S1_26_2);
assign S2_26_1 = S1_26_3;
FA fa80 (S2_28_2,S2_27_0,S1_27_0,S1_27_1,S1_27_2);
assign S2_27_1 = S1_27_3;
FA fa81 (S2_29_1,S2_28_0,S1_28_0,S1_28_1,S1_28_2);
HA ha18 (S2_30_1,S2_29_0,S1_29_0,S1_29_2);
HA ha19 (S2_31_1,S2_30_0,S1_30_0,S1_30_2);
HA ha20 (S2_32_Carry_0,S2_31_0,S1_31_0,S1_31_1);
// ==================== Stage3 ====================
assign S3_0_0 = S2_0_0;
assign S3_1_0 = S2_1_0;
HA ha21 (S3_3_1,S3_2_0,S2_2_0,S2_2_1);
assign S3_3_0 = S2_3_0;
HA ha22 (S3_5_1,S3_4_0,S2_4_0,S2_4_2);
HA ha23 (S3_6_1,S3_5_0,S2_5_0,S2_5_1);
HA ha24 (S3_7_2,S3_6_0,S2_6_0,S2_6_2);
FA fa82 (S3_8_1,S3_7_0,S2_7_0,S2_7_1,S2_7_2);
HA ha25 (S3_9_2,S3_8_0,S2_8_0,S2_8_2);
FA fa83 (S3_10_2,S3_9_0,S2_9_0,S2_9_1,S2_9_2);
FA fa84 (S3_11_2,S3_10_0,S2_10_0,S2_10_1,S2_10_2);
FA fa85 (S3_12_2,S3_11_0,S2_11_0,S2_11_1,S2_11_2);
assign S3_11_1 = S2_11_3;
FA fa86 (S3_13_2,S3_12_0,S2_12_0,S2_12_1,S2_12_2);
FA fa87 (S3_14_2,S3_13_0,S2_13_0,S2_13_1,S2_13_3);
assign S3_13_1 = S2_13_4;
FA fa88 (S3_15_2,S3_14_0,S2_14_0,S2_14_1,S2_14_2);
assign S3_14_1 = S2_14_3;
FA fa89 (S3_16_2,S3_15_0,S2_15_0,S2_15_1,S2_15_3);
assign S3_15_1 = S2_15_4;
FA fa90 (S3_17_2,S3_16_0,S2_16_0,S2_16_1,S2_16_3);
assign S3_16_1 = S2_16_4;
FA fa91 (S3_18_2,S3_17_0,S2_17_0,S2_17_1,S2_17_3);
assign S3_17_1 = S2_17_4;
FA fa92 (S3_19_2,S3_18_0,S2_18_0,S2_18_1,S2_18_3);
assign S3_18_1 = S2_18_4;
FA fa93 (S3_20_2,S3_19_0,S2_19_0,S2_19_1,S2_19_3);
assign S3_19_1 = S2_19_4;
FA fa94 (S3_21_2,S3_20_0,S2_20_0,S2_20_1,S2_20_3);
assign S3_20_1 = S2_20_4;
FA fa95 (S3_22_2,S3_21_0,S2_21_0,S2_21_1,S2_21_3);
assign S3_21_1 = S2_21_4;
FA fa96 (S3_23_2,S3_22_0,S2_22_0,S2_22_1,S2_22_2);
assign S3_22_1 = S2_22_3;
FA fa97 (S3_24_2,S3_23_0,S2_23_0,S2_23_1,S2_23_2);
assign S3_23_1 = S2_23_3;
FA fa98 (S3_25_2,S3_24_0,S2_24_0,S2_24_1,S2_24_2);
FA fa99 (S3_26_2,S3_25_0,S2_25_0,S2_25_1,S2_25_2);
FA fa100 (S3_27_2,S3_26_0,S2_26_0,S2_26_1,S2_26_2);
FA fa101 (S3_28_1,S3_27_0,S2_27_0,S2_27_1,S2_27_2);
HA ha26 (S3_29_1,S3_28_0,S2_28_0,S2_28_2);
HA ha27 (S3_30_1,S3_29_0,S2_29_0,S2_29_1);
HA ha28 (S3_31_1,S3_30_0,S2_30_0,S2_30_1);
HA ha29 (S3_32_Carry_0,S3_31_0,S2_31_0,S2_31_1);
// ==================== Stage4 ====================
assign S4_0_0 = S3_0_0;
assign S4_1_0 = S3_1_0;
assign S4_2_0 = S3_2_0;
HA ha30 (S4_4_1,S4_3_0,S3_3_0,S3_3_1);
assign S4_4_0 = S3_4_0;
HA ha31 (S4_6_1,S4_5_0,S3_5_0,S3_5_1);
HA ha32 (S4_7_1,S4_6_0,S3_6_0,S3_6_1);
HA ha33 (S4_8_1,S4_7_0,S3_7_0,S3_7_2);
HA ha34 (S4_9_1,S4_8_0,S3_8_0,S3_8_1);
HA ha35 (S4_10_1,S4_9_0,S3_9_0,S3_9_2);
HA ha36 (S4_11_2,S4_10_0,S3_10_0,S3_10_2);
FA fa102 (S4_12_1,S4_11_0,S3_11_0,S3_11_1,S3_11_2);
HA ha37 (S4_13_2,S4_12_0,S3_12_0,S3_12_2);
FA fa103 (S4_14_2,S4_13_0,S3_13_0,S3_13_1,S3_13_2);
FA fa104 (S4_15_2,S4_14_0,S3_14_0,S3_14_1,S3_14_2);
FA fa105 (S4_16_2,S4_15_0,S3_15_0,S3_15_1,S3_15_2);
FA fa106 (S4_17_2,S4_16_0,S3_16_0,S3_16_1,S3_16_2);
FA fa107 (S4_18_2,S4_17_0,S3_17_0,S3_17_1,S3_17_2);
FA fa108 (S4_19_2,S4_18_0,S3_18_0,S3_18_1,S3_18_2);
FA fa109 (S4_20_2,S4_19_0,S3_19_0,S3_19_1,S3_19_2);
FA fa110 (S4_21_2,S4_20_0,S3_20_0,S3_20_1,S3_20_2);
FA fa111 (S4_22_2,S4_21_0,S3_21_0,S3_21_1,S3_21_2);
FA fa112 (S4_23_2,S4_22_0,S3_22_0,S3_22_1,S3_22_2);
FA fa113 (S4_24_1,S4_23_0,S3_23_0,S3_23_1,S3_23_2);
HA ha38 (S4_25_1,S4_24_0,S3_24_0,S3_24_2);
HA ha39 (S4_26_1,S4_25_0,S3_25_0,S3_25_2);
HA ha40 (S4_27_1,S4_26_0,S3_26_0,S3_26_2);
HA ha41 (S4_28_1,S4_27_0,S3_27_0,S3_27_2);
HA ha42 (S4_29_1,S4_28_0,S3_28_0,S3_28_1);
HA ha43 (S4_30_1,S4_29_0,S3_29_0,S3_29_1);
HA ha44 (S4_31_1,S4_30_0,S3_30_0,S3_30_1);
HA ha45 (S4_32_Carry_0,S4_31_0,S3_31_0,S3_31_1);
// ==================== Final 2 PPs ====================
assign final_pp0 = {S4_31_0,S4_30_0,S4_29_0,S4_28_0,S4_27_0,S4_26_0,S4_25_0,S4_24_0,S4_23_0,S4_22_0,S4_21_0,S4_20_0,S4_19_0,S4_18_0,S4_17_0,S4_16_0,S4_15_0,S4_14_0,S4_13_0,S4_12_0,S4_11_0,S4_10_0,S4_9_0,S4_8_0,S4_7_0,S4_6_0,S4_5_0,S4_4_0,S4_3_0,S4_2_0,S4_1_0,S4_0_0};
assign final_pp1 = {S4_31_1,S4_30_1,S4_29_1,S4_28_1,S4_27_1,S4_26_1,S4_25_1,S4_24_1,S4_23_2,S4_22_2,S4_21_2,S4_20_2,S4_19_2,S4_18_2,S4_17_2,S4_16_2,S4_15_2,S4_14_2,S4_13_2,S4_12_1,S4_11_2,S4_10_1,S4_9_1,S4_8_1,S4_7_1,S4_6_1,1'b0,S4_4_1,1'b0,1'b0,1'b0,1'b0};

// ==================== compress ====================

   
   
   // ==================== the final CPA ====================
   assign o_result = final_pp0 + final_pp1;
   
   
   

   logic signed [31:0] correct_result;
   logic signed [31:0] tmp_result;

   bit 		       flag;
   initial begin
      #10
	$display("========== multiply : %d * %d", $signed(a_16), $signed(b_16));
      

      // ==================== for simulation ====================
      //booth2 recoding 
      for(int i=0;i<=16;i+=2)	// total 9
	begin
	   booth_array_sim[i/2] = b_16_ext[i] + b_16_ext[i+1] - 2*b_16_ext[i+2]; // 0,+-1,+-2
	   $display("booth_array[%d] = %d", i/2, booth_array_sim[i/2]);
	end
      //gen actual value of PPs for verify
      for(int i=0;i<=8;i++)
	begin
	   pp_actual_sim[i] = $signed(a_16) * booth_array_sim[i];
	   $display("actual PP[%d] = %d(%x)", i, pp_actual_sim[i], pp_actual_sim[i]);
	end
      tmp_result = 0;
      for(int i=0;i<=8;i++)
	tmp_result += pp_actual_sim[i]<<(i*2); // remember the shift
      $display("========== the sum of actual PPs is %d(%x)", tmp_result, tmp_result);
      
      // gen PPs and S, E
      for(int i=0;i<=8;i++)
	begin
	   case(booth_array_sim[i])
	     3'd0:
	       begin
		  pp_sim[i] = '0;
	       end
	     3'd1:
	       pp_sim[i] = a_16;
	     3'd2:
	       pp_sim[i] = a_16<<1;
	     -3'd1:
	       pp_sim[i] = ~a_16;
	     -3'd2:
	       pp_sim[i] = ~(a_16<<1);
	   endcase // case (booth_array_sim[i])
	   //S (the same as the sign of booth_array_sim[i])
	   if(booth_array_sim[i] < 0)
	     S_sim[i] = 1'b1;
	   else
	     S_sim[i] = 1'b0;
	   //E
	   E_sim[i] = (booth_array_sim[i] == 3'd0) ? 1'b1 : S_sim[i] ~^ a_16[16];
	end // for (int i=0;i<=8;i++)


      flag = 1;
      $display("check the correctness of all PPs");
      for(int i=0;i<=8;i++)
	begin
	   flag &= (pp[i] == pp_sim[i]);
	   $display("pp[%d]=%x\tpp_sim[%d]=%x  => %s", i, pp[i], i, pp_sim[i], pp[i]==pp_sim[i] ? "equal" : "!!! not equal !!!");
	end
      if(flag)
	$display("========== all PPs are correct");
      else
	$display("*E: some PPs are error !");

      flag = 1;
      for(int i=0;i<=8;i++)
	begin
	   flag &= (S[i] == S_sim[i]);
	   $display("S[%d]=%d\tS_sim[%d]=%d  => %s", i, S[i], i, S_sim[i], S[i]==S_sim[i] ? "equal" : "!!! not equal !!!");
	end
      if(flag)
	$display("========== all S are correct");
      else
	$display("*E: some S are error !");

      flag = 1;
      for(int i=0;i<=8;i++)
	begin
	   flag &= (E[i] == E_sim[i]);
	   $display("E[%d]=%d\tE_sim[%d]=%d  => %s", i, E[i], i, E_sim[i], E[i]==E_sim[i] ? "equal" : "!!! not equal !!!");
	end
      if(flag)
	$display("========== all E are correct");
      else
	$display("*E: some E are error !");

      // add each column
      cols_sim[0] = pp_sim[0][0] + S_sim[0];
      cols_sim[1] = pp_sim[0][1];
      cols_sim[2] = pp_sim[0][2] + pp_sim[1][0] + S_sim[1];
      cols_sim[3] = pp_sim[0][3] + pp_sim[1][1];
      cols_sim[4] = pp_sim[0][4] + pp_sim[1][2] + pp_sim[2][0] + S_sim[2];
      cols_sim[5] = pp_sim[0][5] + pp_sim[1][3] + pp_sim[2][1];
      cols_sim[6] = pp_sim[0][6] + pp_sim[1][4] + pp_sim[2][2] + pp_sim[3][0] + S_sim[3];
      cols_sim[7] = pp_sim[0][7] + pp_sim[1][5] + pp_sim[2][3] + pp_sim[3][1];
      cols_sim[8] = pp_sim[0][8] + pp_sim[1][6] + pp_sim[2][4] + pp_sim[3][2] + pp_sim[4][0] + S_sim[4];
      cols_sim[9] = pp_sim[0][9] + pp_sim[1][7] + pp_sim[2][5] + pp_sim[3][3] + pp_sim[4][1];
      cols_sim[10] = pp_sim[0][10] + pp_sim[1][8] + pp_sim[2][6] + pp_sim[3][4] + pp_sim[4][2] + pp_sim[5][0] + S_sim[5];
      cols_sim[11] = pp_sim[0][11] + pp_sim[1][9] + pp_sim[2][7] + pp_sim[3][5] + pp_sim[4][3] + pp_sim[5][1];
      cols_sim[12] = pp_sim[0][12] + pp_sim[1][10] + pp_sim[2][8] + pp_sim[3][6] + pp_sim[4][4] + pp_sim[5][2] + pp_sim[6][0] + S_sim[6];
      cols_sim[13] = pp_sim[0][13] + pp_sim[1][11] + pp_sim[2][9] + pp_sim[3][7] + pp_sim[4][5] + pp_sim[5][3] + pp_sim[6][1];
      cols_sim[14] = pp_sim[0][14] + pp_sim[1][12] + pp_sim[2][10] + pp_sim[3][8] + pp_sim[4][6] + pp_sim[5][4] + pp_sim[6][2] + pp_sim[7][0] + S_sim[7];
      cols_sim[15] = pp_sim[0][15] + pp_sim[1][13] + pp_sim[2][11] + pp_sim[3][9] + pp_sim[4][7] + pp_sim[5][5] + pp_sim[6][3] + pp_sim[7][1];
      cols_sim[16] = pp_sim[0][16] + pp_sim[1][14] + pp_sim[2][12] + pp_sim[3][10] + pp_sim[4][8] + pp_sim[5][6] + pp_sim[6][4] + pp_sim[7][2] + pp_sim[8][0];
      cols_sim[17] = {~E_sim[0]} + pp_sim[1][15] + pp_sim[2][13] + pp_sim[3][11] + pp_sim[4][9] + pp_sim[5][7] + pp_sim[6][5] + pp_sim[7][3] + pp_sim[8][1];
      cols_sim[18] = {~E_sim[0]} + pp_sim[1][16] + pp_sim[2][14] + pp_sim[3][12] + pp_sim[4][10] + pp_sim[5][8] + pp_sim[6][6] + pp_sim[7][4] + pp_sim[8][2];
      cols_sim[19] = E_sim[0] + E_sim[1] + pp_sim[2][15] + pp_sim[3][13] + pp_sim[4][11] + pp_sim[5][9] + pp_sim[6][7] + pp_sim[7][5] + pp_sim[8][3];
      cols_sim[20] = 1 + pp_sim[2][16] + pp_sim[3][14] + pp_sim[4][12] + pp_sim[5][10] + pp_sim[6][8] + pp_sim[7][6] + pp_sim[8][4];
      cols_sim[21] = E_sim[2] + pp_sim[3][15] + pp_sim[4][13] + pp_sim[5][11] + pp_sim[6][9] + pp_sim[7][7] + pp_sim[8][5];
      cols_sim[22] = 1 + pp_sim[3][16] + pp_sim[4][14] + pp_sim[5][12] + pp_sim[6][10] + pp_sim[7][8] + pp_sim[8][6];
      cols_sim[23] = E_sim[3] + pp_sim[4][15] + pp_sim[5][13] + pp_sim[6][11] + pp_sim[7][9] + pp_sim[8][7];
      cols_sim[24] = 1 + pp_sim[4][16] + pp_sim[5][14] + pp_sim[6][12] + pp_sim[7][10] + pp_sim[8][8];
      cols_sim[25] = E_sim[4] + pp_sim[5][15] + pp_sim[6][13] + pp_sim[7][11] + pp_sim[8][9];
      cols_sim[26] = 1 + pp_sim[5][16] + pp_sim[6][14] + pp_sim[7][12] + pp_sim[8][10];
      cols_sim[27] = E_sim[5] + pp_sim[6][15] + pp_sim[7][13] + pp_sim[8][11];
      cols_sim[28] = 1 + pp_sim[6][16] + pp_sim[7][14] + pp_sim[8][12];
      cols_sim[29] = E_sim[6] + pp_sim[7][15] + pp_sim[8][13];
      cols_sim[30] = 1 + pp_sim[7][16] + pp_sim[8][14];
      cols_sim[31] = E_sim[7] + pp_sim[8][15];
      
      for(int i=0;i<=31;i++)
	$display("cols_sim[%d] = %d", i, cols_sim[i]);
      
      result = 0;
      for(int i=0;i<=31;i++)
	begin
	   result += cols_sim[i]<<i;
	end
      $display("after compress result = %d (%x)", $signed(result), result);
      

      result = 0;
      result += final_pp0;
      result += final_pp1;
      $display("after wallace compress, result = %d (%x)", $signed(result), result);
      
  
      // #20
      // 	$display("a*b = %d * %d", $signed(a_16), $signed(b_16));
      // result = 0;
	  // for(int i=0;i<9;i++)
      // 	begin
	  // 	   result += pp[i]<<(i*2); // must add the S and E ???
	  // 	   $display("pp[%d] = %x, S[%d] = %d, E[%d] = %d", i, pp[i], i, S[i], i, E[i]);
	  // 	end
	  // $display("result : %x(%d)", result, $signed(result));

	  // correct_result = $signed(a_16)*$signed(b_16);
	  // $display("correct result : %x(%d)", correct_result, correct_result);
	  // if(result == correct_result)
	  // 	$display("========== result correct ==========");
	  // else
	  // 	$display("========== result error ==========");
   end
   

endmodule // booth2_16x16_8x8
